<?php
/**
 * Created by PhpStrom
 * User: 郭碧云
 * Date: 2021/3/10 9:13
 * Desc:
 */

namespace App\Service;


use App\Lib\Common;
use App\Models\Admin\AdminUser;
use App\Models\Admin\Menu;
use App\Models\Admin\ModelHasRoles;
use App\Models\Admin\Org;
use App\Models\Admin\Permission;
use App\Models\Admin\PermissionOrg;
use App\Models\Admin\Role;
use App\Models\Admin\Menu as MenuModel;
use App\Models\Category;
use App\Models\PermissionCategory;
use Illuminate\Routing\Exceptions\UrlGenerationException;
use Illuminate\Support\Arr;
use Illuminate\Support\Facades\DB;

class AuthService
{
    /**
     * 角色部分
     */
    //获取全部列表
    public function getAll($params)
    {
        //where条件
        if (array_key_exists("name", $params) && (!empty($params["name"]) || $params["name"] != null || $params["name"] != "")) {
            $params["name"] = ["%" . $params["name"] . "%"];
        }
        $size = array_key_exists("limit", $params) && $params["limit"] > 0 ? $params["limit"] : config("model.pagesize");
        //获取数据
        $result = (new Role())->getAll($params, $size);
        for ($i = 0; $i < count($result["data"]); $i++) {
            empty($result["data"][$i]["site"]) || null == $result["data"][$i]["site"] ? $result["data"][$i]["site"]["name"] = '平台' : "";
        }
        return $result;
    }

    //添加
    public function create($params, $site_id)
    {
        $params["site_id"] = $site_id;
        //排重
        $isHas = Role::hasRole($params['name'], $site_id);
        if (!empty($isHas)) {
            return ["error" => 80002, "msg" => "请不要重复添加角色"];
        }
        //插入数据
        return Role::create($params);
    }

    //获取一个角色
    public function getOne($id)
    {
        return (new Role())->getOne($id);
    }

    //修改角色
    public function update($params, $id)
    {
        return (new Role())->change($params, $id);
    }

    //删除角色
    public function delete($id)
    {
        return (new Role())->destoryOne($id);
    }

    //角色详情
    public function getInfo(Role $role)
    {
        //获取角色
        $data = (new Role())->info($role);
        if (empty($data["site"]) || null == $data["site"]) {
            $data["site"]["name"] = "平台";
        }
        return $data;
    }

    /**
     * 权限部分
     */
    //获取全部列表
    public function getPermission($params)
    {
        //where条件
        $where = [];
        if (array_key_exists("display_name", $params) && (!empty($params["display_name"]) || $params["display_name"] != null || $params["display_name"] != "")) {
            $where[] = ["display_name", "like", "%" . $params["display_name"] . "%"];
        }
        //下拉菜单选项
        if (array_key_exists("flag", $params) && $params["flag"] == "select") {
            $where[] = ["type", "=", 1];
            $result = (new Permission())->where("type", 1)->get()->toArray();
            $data = [];
            for ($i = 0; $i < count($result); $i++) {
                $data[$i]["id"] = $result[$i]["id"];
                $data[$i]["parent_id"] = $result[$i]["parent_id"];
                $data[$i]["name"] = $result[$i]["display_name"];
            }
            return $data;
        }
        //获取数据
        return (new Permission())->getAll($where);
    }

    //获取一个权限
    public function getOnePer($id)
    {
        return (new Permission())->getOne($id);
    }

    //添加权限
    public function store($params, $site_id)
    {
        $params["site_id"] = $site_id;
        //排重
        $isHas = Permission::hasPermission($params['name'], $site_id, getCurrentUser()['guard_name']);
        if (!empty($isHas)) {
            return ["error" => 80002, "msg" => "请不要重复添加权限"];
        }
        if (array_key_exists("type", $params) && ($params["type"] == 2)) {
            //检查路由是否存在
            $route = $this->checkRoute($params["name"]);
            if ($route != 1) {
                return ["flag" => "", "route" => $route];
            }
        }
        unset($params["select"]);
        //插入数据
        return Permission::create($params);
    }

    //将权限分配给超级管理员
    public function assignAdmin($permission)
    {
        //获取角色
        $role = (new \Spatie\Permission\Models\Role())->find(1);
        $role->givePermissionTo($permission);
    }

    //修改权限
    public function change($params, $id)
    {
        //检查路由是否存在
        if ((array_key_exists("type", $params) && $params["type"] == 2) || !array_key_exists("type", $params)) {
            //检查路由是否存在
            $route = $this->checkRoute($params["name"]);
            if ($route != 1) {
                return $route;
            }
        }
        //更新
        return (new Permission())->change($params, $id);
    }

    //获取权限信息
    public function getInfoPer(Permission $permission)
    {
        return (new Permission())->info($permission);
    }

    //更改权限可操作状态
    public function noOroff($params)
    {
        return (new Permission())->status($params['status'], $params['id']);
    }

    //检查路由是否存在
    public function checkRoute($uri)
    {
        $routes = Common::get_route_name();
        //没有路由
        if (empty($routes)) {
            return 0;
        }
        //路由是否存在
        $flag = 0;
        foreach ($routes as $key => $value) {
            if ($value == $uri) {
                $flag = 1;
            }
        }
        return $flag == 1 ? 1 : 2;
    }

    //分配权限
    public function assign_permission($rold_id, $permission)
    {
        //获取权限
        $permission = array_values($permission);
        //获取角色
        $role = (new \Spatie\Permission\Models\Role())->find($rold_id);
        if (empty($role)) {
            return ["error" => 70000, "msg" => "角色不存在"];
        }
        //赋予权限
        return $role->syncPermissions($permission);
    }

    //获取角色已有权限
    public function has_permission($role_id)
    {
        //获取角色
        $role = (new \Spatie\Permission\Models\Role())->find($role_id);
//        return $role->getPermissionNames()->toArray();

        return $role->getAllPermissions()->toArray();
    }

    /**
     * 菜单相关
     */
    //获取父栏目菜单
    public function getParent($id)
    {
        if ($id > 0) {
            $result = (new MenuModel())->getFInfo($id);
        } else {
            $result = ["id" => 0, "parent_id" => 0, "name" => "顶部菜单"];
        }
        return $result;
    }

    //验证路由
    public function checkMenuRoute($params)
    {
        //检查路由是否存在
        $route = $this->check_permission_name($params["uri"], getCurrentSiteId());
        if (empty($route) || (is_array($route) && array_key_exists("error", $route) && $route["error"] > 0)) {
            return ["error" => 70000, "uri" => "admin.menu.index", "msg" => "所加路由没有授权"];
        }
        $params["permission_id"] = array_key_exists("data", $route) && $route["data"][0]->id >= 0 ? $route["data"][0]->id : $route[0]->id;
        //获取路由参数
        if (array_key_exists('data', $params) && !empty($params["data"])) {
            $params["data"] = json_encode($this->checkRouteParam($params["data"]));
        }
        //验证路由参数是否完整
        try {
            route($params['uri'], json_decode($params["data"], true));
        } catch (UrlGenerationException $e) {
            return ["error" => 90001, "uri" => "admin.menu.index", "msg" => "路由参数错误"];
        }
        return ["error" => 0, "uri" => "", "data" => $params];
    }

    //检查菜单添加的路由，在权限中是否存在
    public function check_permission_name($name, $site_id)
    {
        //权限表uri
        $name = preg_replace("/.attach(.[\d]+){0,1}$/", "", $name);
        $routes = (new Permission())->terim($name, $site_id);
        //没有路由
        return $routes;
    }

    //检查路由参数是否存在
    protected function checkRouteParam($data)
    {
        //拆分字符串为数组
        $arr = explode("\r\n", $data);
        $params = [];
        //重组数组
        foreach ($arr as $a) {
            $item = explode("|", $a);
            $params[$item[0]] = $item[1];
        }
        return $params;
    }

    //获取权限列表，分配权限
    public function per_form($guardName)
    {
        $list = (new Permission())->get_per_list($guardName)->toArray();
        //结果处理
        if (empty($list)) {
            return ["error" => 80000, "msg" => "没有权限"];
        }
        //返回权限树处理(todo 用户自己的权限)
        //todo 最高管理员用户，分配权限，开发环境中保留
        if (getCurrentUser()["site_id"] == 0) {
            //todo 最高管理员用户，分配权限，生产环境中保留
            $tree = Common::getTree($list);
        } else {
            //过滤不可操作数据
            $list = $this->filterPermission($list);
            //todo 最高管理员用户，分配权限，开发环境中保留
            $data = (new Permission())->get()->toArray();
            $temp = Common::father_list($list, $data);
            $total = array_merge($list, $temp);
            $get_data = Common::array_unset_tt($total, "id");
            $tree = Common::getTree($get_data);
        }
        return $tree;
    }

    /**
     * 过滤不可操作权限
     */
    private function filterPermission($list)
    {
        $newlist = [];
        foreach ($list as $k => $v) {
            if ($v["status"] == 1) {
                $newlist[] = $v;
            }
        }
        return $newlist;
    }

    /**
     * 用户相关
     */
    //获取全部角色
    public function get_roles()
    {
        return (new Role())->get_roles();
    }

    //分配角色
    public function assignRole(AdminUser $user, $val)
    {
        //获取角色
        $role = array_values($val["data"]["roles"]);
        //赋予角色
        $result = $user->syncRoles($role)->toArray();
        if (empty($result)) {
            return ['error' => 200000, 'msg' => "角色赋予失败"];
        }
        //给角色添加时间
        $data = $this->getRoleUpdate($result["roles"], $val["data"]["expire_at"]);
        (new ModelHasRoles())->updateExpire($data);
        //分配管理范围
        if (session("guard") != "system") {
            $result = $this->assignArea($user, $val["data"]);
            if ($result['orgs'] < 0 && $result["category"] < 0) {
                return ["error" => 70000, "msg" => "权限分配失败"];
            }
        }
        return ['error' => 0, 'msg' => "权限分配成功"];
    }

    //获取用户拥有的角色
    public function hasUserRoles(AdminUser $user)
    {
        $roleModel = new Role();
        $modelHasRoles =new ModelHasRoles();
        $userInfo = (new AdminUser())->getUserRoles($user)->toArray();
        $roles = $userInfo["role"];
        $data = [];
        //管理员角色
        $roleSite = $modelHasRoles->isStieRole($userInfo["id"])->toArray();
        if (!empty($roleSite)) {
            $roleInfo = $roleModel->withoutGlobalScope('site_id_scope')->where("id",$roleSite[0]["role_id"])->first()->toArray();
            $data[0]["name"]=$roleInfo["name"];
            $data[0]["expire_at"] = $roleSite[0]["expire_at"];
        }
        $i = count($data)>0?1:0;
        //系统角色
        $isSystems = $roleModel->withoutGlobalScope('site_id_scope')->where("is_system",1)->where("id",">",2)->get()->toArray();
        if(!empty($isSystems)){
            //提取系统角色
            $roleSystem=$roleModel->withoutGlobalScope('site_id_scope')->whereIn("id",Arr::pluck($isSystems, 'id'))->get()->toArray();
            $userHasSystemRole = $modelHasRoles->whereIn("role_id",Arr::pluck($isSystems, 'id'))->where("model_id",$userInfo["id"])->get()->toArray();
            if(!empty($userHasSystemRole)){
                for ($j=0;$j<count($userHasSystemRole);$j++){
                    foreach ($roleSystem as $v){
                        if($v["id"]==$userHasSystemRole[$j]["role_id"]){
                            $data[$i]["name"]=$v["name"];
                            $data[$i]["expire_at"]=$userHasSystemRole[$j]["expire_at"];
                            $i++;
                        }
                    }
                }
            }
        }
        //重置$i的初始值
        $i = count($data)>0?count($data):0;
        //站点角色
        for ($k=0 ; $k < count($roles); $k++) {
            $data[$i]["name"] = $roles[$k]["name"];
            $data[$i]["expire_at"] = $roles[$k]["pivot"]["expire_at"];
            $i++;
        }
        return $data;

    }

    /**
     * 分配管理范围
     */
    private function assignArea(AdminUser $user, $vals)
    {
        $select = $vals["select"];
        $categories = $vals["categories"];
        $orgs = $this->assignOrg($user, $select);
        $category = $this->assignCategory($user, $categories);
        return ["orgs" => $orgs, "category" => $category];
    }

    /**
     * 分配组织机构管理范围
     * @param $ids 分配的管理机构的id字符串 例：1,2,3.....
     */
    private function assignOrg(AdminUser $user, $ids)
    {
        $id_arr = explode(",", $ids);
        $creator = getCurrentUser()["id"];
        //获取用户已经拥有的机构
        $hasIds = (new PermissionOrg())->where("user_id", $user->toArray()['id'])->pluck("org_id")->toArray();
        $data = $this->assignOrgData($id_arr, $user->toArray()['id'], $creator);
        $this->assignOrgDel($hasIds, $id_arr, $user->toArray()["id"]);
        return (new PermissionOrg())->insertOrIgnore($data);
    }

    /**
     * 分配可管理的科目
     * @param $ids 分配的科目的id字符串 例：1,2,3.....
     */
    private function assignCategory(AdminUser $user, $ids)
    {
        $id_arr = explode(",", $ids);
        $creator = getCurrentUser()["id"];
        //获取用户已经拥有的科目
        $hasIds = (new PermissionCategory())->whereBuilder(["user_id" => $user->toArray()['id']])->pluck("category_id")->toArray();
        $data = $this->assignCategoryData($id_arr, $user->toArray()['id'], $creator);
        $this->assignOrgDel($hasIds, $id_arr, $user->toArray()["id"], 2);
        return (new PermissionCategory())->insertOrIgnore($data);
    }

    /**
     * 获取可分配的科目
     * 1.管理员操作所有科目
     * 2.非管理员操作自己的科目
     * @param $where 条件
     */
    public function getCategory($where, $filed = "*")
    {
        $isSite = (new ModelHasRoles())->isStieRole(getCurrentUser()['id'])->toArray();
        //管理员
        $allCategory = (new CategoryService("category"))->getAll($filed, $where);
        //系统管理员
        if (getCurrentSiteId() == 0) {
            return $this->addDisabled($allCategory, []);
        }
        //非管理员
        if (empty($isSite) && getCurrentSiteId() > 0) {
            //用户已有分类
            $category = (new AdminUser())->with("category")->where("id",getCurrentUser()['id'])->first()->toArray();
            $father = Common::father_list($category["category"], $allCategory);
            $data = Common::array_unset_tt(array_merge($category["category"], $father),"id");
            $data = $this->addDisabled($data, $category);
            return $data;
        }
        return $allCategory;
    }

    /**
     * 获取父子全部数据
     * @param $data 用户拥有的分类
     */
    private function getAllData($data, $where = [])
    {
        if (empty($data)) {
            return [];
        }
        //获取顶级父类path
        $father = [];
        foreach ($data as $k => $v) {
            $item = explode(".", $v["path"]);
            $father[$k] = $item[0] . ".";
        }
        $father = array_unique($father);
        //获取数据
        $categorise = [];
        foreach ($father as $v) {
            $item = (new Category())->whereBuilder($where)->where("path", "like", $v . "%")->get()->toArray();
            $temp = array_map(function ($i) {
                return $i;
            }, $item);
            $categorise = array_merge($categorise, $temp);
        }
        return $categorise;
    }

    /**
     * 获取用户拥有的分类
     * @param $userid 用户id
     */
    public function userHasCategory($userid)
    {
        $data = (new PermissionCategory())->whereBuilder(["user_id" => $userid])->pluck('category_id');
        return !empty($data) ? $data->toArray() : [];
    }

    //添加禁止字段
    protected function addDisabled($data, $category)
    {
        foreach ($data as $k => $d) {
            if (!in_array($d['id'], $category)) {
                $data[$k]['disabled'] = true;
            }
        }
        return $data;
    }

    /**
     * 获取分配的组织机构
     * 更新/插入数据
     */
    private function assignOrgData($id_arr, $user_id, $creator)
    {
        $org = new Org();
        //整理数据
        $data = [];
        //获取父类组织机构
        $sonList = $org->whereIn("id", $id_arr)->get(["id", "parent_id", "code"])->toArray();
        $allList = $org->get(["id", "parent_id", "code"])->toArray();
        $father = Common::father_list($sonList, $allList);
        $getData = array_merge($sonList, $father);
        //获取组织机构code码
        foreach ($getData as $id) {
            $temp["user_id"] = $user_id;
            $temp["org_id"] = $id["id"];
            $temp['org_code'] = $id["code"];
            $temp["creator"] = $creator;
            array_push($data, $temp);
        }
        return $data;
    }

    /**
     * 获取分配的科目分类
     * 更新/插入数据
     */
    private function assignCategoryData($id_arr, $user_id, $creator)
    {
        $category = new Category();
        //整理数据
        $data = [];
        //获取父类组织机构
        $sonList = $category->whereIn("id", $id_arr)->get(["id", "parent_id","path"])->toArray();
        $allList = $category->get(["id", "parent_id","path"])->toArray();
        $father = Common::father_list($sonList, $allList);
        $getData = array_merge($sonList, $father);
        foreach ($getData as $k => $id) {
            $data[$k]["user_id"] = $user_id;
            $data[$k]["category_id"] = $id["id"];
            $data[$k]["category_path"] = $id["path"];
            $data[$k]["creator"] = $creator;
            $data[$k]["created_at"] = time();
            $data[$k]["updated_at"] = time();
        }
        return $data;
    }

    /**
     * 删除多余数据
     * @param $hasIds 拥有的id
     * @param $id_arr 拥有的id
     * @param $id 用户id
     * @param $type 1表示组织机构(默认值)，2表示科目分类
     *
     */
    private function assignOrgDel($hasIds, $id_arr, $id, $type = 1)
    {
        $delIds = [];
        //是否含有多余数据
        foreach ($hasIds as $orgId) {
            if (!in_array($orgId, $id_arr)) {
                $delIds[] = $orgId;
            }
        }
        //删除多余数据
        switch ($type) {
            case 1:
                (new PermissionOrg())->where("user_id", $id)->whereIn('org_id', $delIds)->delete();
                break;
            case 2:
                (new PermissionCategory())->whereBuilder(["user_id" => $id])->whereIn('category_id', $delIds)->delete();
                break;
        }
    }

    /**
     * 读取过期时间
     * @param $roles 全部角色
     * @param $has_role 用户拥有的角色
     */
    public function getExpire($roles, $has_role)
    {
        foreach ($roles as $k => $v) {
            foreach ($has_role as $r) {
                if ($r["name"] == $v["name"]) {
                    if (array_key_exists("expire_at", $r)) {
                        if ($r["expire_at"] > 0) {
                            $roles[$k]["expire_at"] = date("Y-m-d", $r["expire_at"]);
                        } else {
                            $roles[$k]["expire_at"] = "有效期：无限";
                        }
                    }
                }
            }
        }
        return $roles;
    }

    /**
     * 提取角色用户关联表更新数据
     * @param $roles 用户拥有的角色
     * @param $expire_ats 用户拥有的角色的时间限制
     */
    public function getRoleUpdate($roles, $expire_ats)
    {
        $data = [];
        $i = 0;
        foreach ($roles as $role) {
            $data[$i]["role_id"] = $role["pivot"]["role_id"];
            $data[$i]["model_id"] = $role["pivot"]["model_id"];
            foreach ($expire_ats as $k => $v) {
                if ($role["name"] == $k) {
                    if ($v == null || $v == 0 || empty($v) || $v == "") {
                        $data[$i]["expire_at"] = 0;
                    } else {
                        $data[$i]["expire_at"] = strtotime($v);
                    }
                }
            }
            $i++;
        }
        $i = 0;
        return $data;
    }

    /**
     * 获取可分配的组织机构
     * @param $user_id 当前用户的id
     */
    public function getOrg($user_id)
    {
        $data = getData("OrgDataTag", []);

        //已拥有的组织机构
        $hasOrg = $this->getHasOrg($user_id);
        foreach ($data as $k => $v) {
            if (in_array($v["id"], $hasOrg)) {
                $data[$k]["selected"] = true;
            }
        }
        return Common::getTree($data);
    }

    /**
     * 获取可分配的组织机构
     */
    public function getHasOrg($user_id)
    {
        $data = (new PermissionOrg())->where("user_id", $user_id)->pluck('org_id');
        if (empty($data)) {
            return [];
        }
        $data = $data->toArray();
        return array_values($data);
    }
}
